package com.huijie.core.util.exportexcel;

import com.huijie.core.util.DateUtil;
import com.lowagie.text.*;
import com.lowagie.text.Font;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.List;

/** 
* @ClassName: DataExportUtils 
* @Description: TODO
* @author JsonY 
* @date 2017年9月18日 下午4:51:09 
* 
* @param <T> 
*/
public class DataExportUtils<T> {
	private static final String FONT_PATH="/framework/ui3/fonts/pdf/simsun.ttc,1";
	
	/** 
	* @Title: exportExcel
	* @Description: TODO
	* @param headerOrderMap
	* @param headerMap
	* @param data
	* @param out
	*/
	@SuppressWarnings({ "rawtypes", "unchecked", "javadoc" })
	public void exportExcel(Map<Integer,String> headerOrderMap,Map<Integer,String> headerMap,List<T> data,OutputStream out) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException{
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet();
		sheet.setDefaultColumnWidth(20);
		
		HSSFFont font = workbook.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		
		HSSFCellStyle style = workbook.createCellStyle();
		style.setFont(font);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setBorderBottom(HSSFBorderFormatting.BORDER_THIN);
		style.setBottomBorderColor(HSSFColor.GREY_50_PERCENT.index);
//		style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,#0"));  
		//style.setFillBackgroundColor(HSSFColor.GREY_40_PERCENT.index);
		
		HSSFRow row = sheet.createRow(0);
		Set<Integer> keys=headerMap.keySet();
		Iterator<Integer> iterator=keys.iterator();
		while(iterator.hasNext()){
			Integer key=iterator.next();
			HSSFCell cell = row.createCell(key);
			cell.setCellValue(headerMap.get(key));
			cell.setCellStyle(style);
		}
		
		Integer n=1;
		for(T t:data){
			HSSFRow tRow=sheet.createRow(n);
			Class cls=t.getClass();
			for(int i=0;i<headerOrderMap.size();i++){
				HSSFCell cell = tRow.createCell(i);
				String fieldName=headerOrderMap.get(i);
				String getMethodName = "get"
		                   + fieldName.substring(0, 1).toUpperCase()
		                   + fieldName.substring(1);
				Field field = null;
				try{
					field=cls.getDeclaredField(fieldName);
				}catch(NoSuchFieldException noField){
					//
				}
				Method getMethod=null;
				if(field!=null){
					getMethod = cls.getMethod(getMethodName);
				}else{
					Class superCls=cls.getSuperclass();
					getMethod = superCls.getMethod(getMethodName);
				}
				Object value = getMethod.invoke(t);
				if(value!=null){
					if(value instanceof Date){
						Date dateVal=(Date)value;
						cell.setCellValue(DateUtil.formatDate(dateVal, DateUtil.DATE_FORMAT_COMMON));
					}else if("getMinAllocationStock".equalsIgnoreCase(fieldName)){
//						style.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,#0"));
						cell.setCellValue(Integer.parseInt(value.toString()));
						cell.setCellStyle(style);
					}else{
						cell.setCellValue(value.toString());
					}
				}
			}
			n++;
		}
		
		workbook.write(out);
	}
	
	@SuppressWarnings({"rawtypes", "javadoc"})
	public void exportExcelJson(Map<Integer,String> headerOrderMap, Map<Integer,String> headerMap, JSONArray jsonData, OutputStream out) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException{
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet();
		sheet.setDefaultColumnWidth(20);
		
		HSSFFont font = workbook.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		
		HSSFCellStyle style = workbook.createCellStyle();
		style.setFont(font);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setBorderBottom(HSSFBorderFormatting.BORDER_THIN);
		style.setBottomBorderColor(HSSFColor.GREY_50_PERCENT.index);
		//style.setFillBackgroundColor(HSSFColor.GREY_40_PERCENT.index);
		
		HSSFRow row = sheet.createRow(0);
		Set<Integer> keys=headerMap.keySet();
		Iterator<Integer> iterator=keys.iterator();
		while(iterator.hasNext()){
			Integer key=iterator.next();
			HSSFCell cell = row.createCell(key);
			cell.setCellValue(headerMap.get(key));
			cell.setCellStyle(style);
		}
		
		Integer n=1;
		Iterator jsonIterator=jsonData.iterator();
		while(jsonIterator.hasNext()){
			HSSFRow tRow=sheet.createRow(n);
			JSONObject jsonObject=(JSONObject)jsonIterator.next();
			iterator=keys.iterator();
			while(iterator.hasNext()){
				Integer key=iterator.next();
				HSSFCell cell = tRow.createCell(key);
				String fieldName=headerOrderMap.get(key);
				if(jsonObject.containsKey(fieldName)) {
					cell.setCellValue(jsonObject.getString(fieldName));
				}
			}
			n++;
		}
		
		workbook.write(out);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes", "javadoc" })
	public void exportPdf(Map<Integer, String> headerOrderMap,Map<Integer,String> headerMap,List<T> data,OutputStream out,HttpServletRequest request) throws DocumentException, SecurityException, NoSuchFieldException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException{
		Document document = new Document(PageSize.A4.rotate(),0,0,10,0);
		PdfWriter.getInstance(document,out);
		document.open();
		int hSize=headerMap.size();
		PdfPTable table = new PdfPTable(hSize+1);
		Font font=getChineseFont(request);
		PdfPCell hnCell = new PdfPCell(new Paragraph("序号",font));
		hnCell.setBackgroundColor(Color.LIGHT_GRAY);
		hnCell.setHorizontalAlignment(Cell.ALIGN_CENTER);
		hnCell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
		table.addCell(hnCell);
		int[] widths=new int[hSize+1];
		widths[0]=2*12+10;
		for(int i=0;i<hSize;i++){
			String txt=headerMap.get(i);
			PdfPCell cell = new PdfPCell(new Paragraph(txt,font));
			cell.setBackgroundColor(Color.LIGHT_GRAY);
			cell.setHorizontalAlignment(Cell.ALIGN_CENTER);
			cell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
			table.addCell(cell);
			int length=txt.length();
			widths[i+1]=(length<5?5:length)*12+10;
		}
		table.setWidths(widths);
		
		Integer n=1;
		for(T t:data){
			Class cls=t.getClass();
			PdfPCell nCell = new PdfPCell(new Paragraph(n.toString(),font));
			nCell.setHorizontalAlignment(Cell.ALIGN_CENTER);
			nCell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
			table.addCell(nCell);
			for(int i=0;i<hSize;i++){
				String fieldName=headerOrderMap.get(i);
				String getMethodName = "get"
		                   + fieldName.substring(0, 1).toUpperCase()
		                   + fieldName.substring(1);
				Field field = null;
				try{
					field=cls.getDeclaredField(fieldName);
				}catch(NoSuchFieldException noField){
					//
				}
				Method getMethod=null;
				if(field!=null){
					getMethod = cls.getMethod(getMethodName);
				}else{
					Class superCls=cls.getSuperclass();
					getMethod = superCls.getMethod(getMethodName);
				}
				Object value = getMethod.invoke(t);
				if(value!=null){
					if(value instanceof Date){
						Date dateVal=(Date)value;
						PdfPCell cell = new PdfPCell(new Paragraph(DateUtil.formatDate(dateVal, DateUtil.DATE_FORMAT_COMMON),font));
						cell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
						table.addCell(cell);
					}else{
						PdfPCell cell = new PdfPCell(new Paragraph(value.toString(),font));
						cell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
						table.addCell(cell);
					}
				}else{
					table.addCell("");
				}
			}
			n++;
		}
		
		document.add(table);
		document.close();
	}
	
	@SuppressWarnings({ "rawtypes", "javadoc" })
	public void exportPdfJson(Map<Integer, String> headerOrderMap, Map<Integer, String> headerMap, JSONArray jsonData, OutputStream out, HttpServletRequest request) throws DocumentException, IOException{
		Document document = new Document(PageSize.A4.rotate(),0,0,10,0);
		PdfWriter.getInstance(document,out);
		document.open();
		int hSize=headerMap.size();
		PdfPTable table = new PdfPTable(hSize+1);
		Font font=getChineseFont(request);
		PdfPCell hnCell = new PdfPCell(new Paragraph("序号",font));
		hnCell.setBackgroundColor(Color.LIGHT_GRAY);
		hnCell.setHorizontalAlignment(Cell.ALIGN_CENTER);
		hnCell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
		table.addCell(hnCell);
		int[] widths=new int[hSize+1];
		widths[0]=2*12+10;
		for(int i=0;i<hSize;i++){
			String txt=headerMap.get(i);
			PdfPCell cell = new PdfPCell(new Paragraph(txt,font));
			cell.setBackgroundColor(Color.LIGHT_GRAY);
			cell.setHorizontalAlignment(Cell.ALIGN_CENTER);
			cell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
			table.addCell(cell);
			int length=txt.length();
			widths[i+1]=(length<5?5:length)*12+10;
		}
		table.setWidths(widths);
		
		Iterator jsonIterator=jsonData.iterator();
		Integer n=1;
		while(jsonIterator.hasNext()){
			PdfPCell nCell = new PdfPCell(new Paragraph(n.toString(),font));
			nCell.setHorizontalAlignment(Cell.ALIGN_CENTER);
			nCell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
			table.addCell(nCell);
			JSONObject jsonObject=(JSONObject)jsonIterator.next();
			for(int i=0;i<hSize;i++){
				String fieldName=headerOrderMap.get(i);
				if(jsonObject.containsKey(fieldName)){
					String value=jsonObject.getString(fieldName);
					PdfPCell cell = new PdfPCell(new Paragraph(value,font));
					cell.setVerticalAlignment(Cell.ALIGN_MIDDLE);
					table.addCell(cell);
				}else{
					table.addCell("");
				}
			}
			n++;
		}
		document.add(table);
		document.close();
	}
	
	@SuppressWarnings("javadoc")
	public void exportExcelForWeb(Map<Integer,String> headerOrderMap,Map<Integer,String> headerMap,List<T> data,String fileName,HttpServletResponse response) throws IOException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
		ServletOutputStream servletOutputStream = null;
		try{
			setExcelResponse(fileName,response);
			servletOutputStream=response.getOutputStream();
			exportExcel(headerOrderMap,headerMap,data,servletOutputStream);
			//servletOutputStream.flush();
		}finally{
			if(servletOutputStream!=null) {
				servletOutputStream.close();
			}
		}
	}
	
	@SuppressWarnings("javadoc")
	public void exportExcelForWebJson(Map<Integer, String> headerOrderMap, Map<Integer, String> headerMap, JSONArray jsonData, String fileName, HttpServletResponse response) throws IOException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
		ServletOutputStream servletOutputStream = null;
		try{
			setExcelResponse(fileName,response);
			servletOutputStream=response.getOutputStream();
			exportExcelJson(headerOrderMap,headerMap,jsonData,servletOutputStream);
			//servletOutputStream.flush();
		}finally{
			if(servletOutputStream!=null) {
				servletOutputStream.close();
			}
		}
	}
	
	@SuppressWarnings("javadoc")
	public void exportPdfForWeb(Map<Integer,String> headerOrderMap,Map<Integer,String> headerMap,List<T> data,String fileName,HttpServletRequest request,HttpServletResponse response) throws IOException, SecurityException, IllegalArgumentException, DocumentException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
		ServletOutputStream servletOutputStream = null;
		try{
			setPdfResponse(fileName,response);
			servletOutputStream=response.getOutputStream();
			exportPdf(headerOrderMap,headerMap,data,servletOutputStream,request);
			//servletOutputStream.flush();
		}finally{
			if(servletOutputStream!=null) {
				servletOutputStream.close();
			}
		}
	}
	
	@SuppressWarnings("javadoc")
	public void exportPdfForWebJson(Map<Integer,String> headerOrderMap, Map<Integer,String> headerMap, JSONArray jsonData, String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException, SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, DocumentException{
		ServletOutputStream servletOutputStream = null;
		try{
			setPdfResponse(fileName,response);
			servletOutputStream=response.getOutputStream();
			exportPdfJson(headerOrderMap,headerMap,jsonData,servletOutputStream,request);
			//servletOutputStream.flush();
		}finally{
			if(servletOutputStream!=null) {
				servletOutputStream.close();
			}
		}
	}
	
	private Font getChineseFont(HttpServletRequest request) throws DocumentException, IOException {
        BaseFont bf = BaseFont.createFont(request.getSession().getServletContext().getRealPath(FONT_PATH),BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        Font fontChinese = new Font(bf, 10, Font.NORMAL);
        return fontChinese;
    }
	
	private void setExcelResponse(String fileName,HttpServletResponse response) throws UnsupportedEncodingException{
		setResponse(fileName,"xls","application/vnd.ms-excel",response);
	}
	
	private void setPdfResponse(String fileName,HttpServletResponse response) throws UnsupportedEncodingException{
		setResponse(fileName,"pdf","application/pdf",response);
	}
	
	private void setResponse(String fileName,String suffix,String mimeType,HttpServletResponse response) throws UnsupportedEncodingException{
		response.setContentType(mimeType);
		response.setHeader("content-disposition", "attachment; filename=" + new String(fileName.getBytes("gbk"), "iso8859-1")+"."+suffix);
		response.setDateHeader("expires", 0);
		response.setHeader("cache-control", "no-cache");
		response.setHeader("pragma", "no-cache");
	}
}
